<?php

namespace Admin\Model;
use Admin\Model\BaseModel;
class AdminMenuModel extends BaseModel
{
    public $tableName = 'admin_menu';
    public $_validate = array(
        array('name', '1,100', '标题必须在1~100之间', 0, 'length', 3)
    );

    /**
     * 查询详情
     * @param int $id 菜单id
     * @return array  菜单信息
     * @throws Exception 数据不存在异常
     */
    public function getMenuInfo($id)
    {
        $menuInfo = $this->where(array('id' => $id))->find();
        if (false === $menuInfo) {
            throw new \Exception('没有信息');
        }
        return $menuInfo;
    }

    /**
     * 通过class_id查找子目录
     * @param string $class_id
     * @param int $tierType 查询最高层数, 0是下一层
     * @return array
     * @throws Exception
     */
    public function getMenuList4ClassId($class_id = '', $tierType = 0)
    {
        $tier_id = strlen($class_id) / 2 + 1;
        if (!empty($class_id)) {
            $where['class_id'] = array(array('like', $class_id . '%'), array('neq', $class_id), 'AND');
        }
        if (empty($tierType)) {
            $where['tier_id'] = $tier_id;
        } else {
            $where['tier_id'] = array('lt', $tierType);
        }
        $menuList = $this->where($where)->order('id desc')->select();
        if (empty($menuList)) {
            return array();
        }
        foreach ($menuList as $key => $value) {
            $menuList[$key]['className'] = $this->getClassName($value['class_id']);
            $menuList[$key]['maxSort'] = $value['orderby'] == $this->getMaxSort($value['class_id']) ? 1 : 0;
            $menuList[$key]['minSort'] = $value['orderby'] == $this->getMinSort($value['class_id']) ? 1 : 0;
        }
        return $menuList;
    }

    /**
     * 通过class_id按树形结构输出目录
     * @param string $class_id
     * @param int $tierType 查询最高层数, 0是下一层
     * @return array
     */
    public function getMenuTree4ClassId($class_id = '', $tierType = 0)
    {
        $menuList = $this->getMenuList4ClassId($class_id, $tierType);
        $res = $this->menu2Tree($menuList);
        return $res;
    }

    /**
     * 将目录顺序按层级分类
     * @param type $menuArray
     */
    private function menu2Tree($menuArray)
    {
        $i = 0;
        $j = 100; //更好的做法是查数据库，得到tier_id的最大值并赋值。这里我偷懒了(*^__^*)
        $tmpArray = array();
        foreach ($menuArray as $key => $value) {
            $i = $value['tier_id'] > $i ? $value['tier_id'] : $i;
            $j = $value['tier_id'] < $j ? $value['tier_id'] : $j;
            $value['class_str'] = 'class_id_' . $value['class_id'];
            $tmpArray[$value['tier_id']][] = $value;
        }
        $min = $j;
        for ($j; $j < $i; $j++) {
            foreach ($tmpArray[$j] as $tmpKey => $tmpValue) {
                foreach ($tmpArray[$j + 1] as $tmpK => $tmpV) {
                    if ($tmpValue['class_id'] == substr($tmpV['class_id'], 0, strlen($tmpValue['class_id']))) {
                        $tmpArray[$tmpValue['class_str']][] = $tmpV;
                    }
                }
            }
        }
        foreach ($tmpArray as $key => $value) {
            if (is_int($key) && $key > $min) {
                unset($tmpArray[$key]);
            } else {
                uasort($tmpArray[$key], function($x, $y) {return ($x['orderby'] > $y['orderby']);});
            }
        }
        return $tmpArray;
    }

    /**
     * 得到class_id的下一个子class_id
     * @param sting $class_id
     * @return sting
     */
    public function getNextChild($class_id)
    {
        try {
            $childMenuList = $this->getMenuList4ClassId($class_id);
            $min = 0;
            foreach ($childMenuList as $key => $value) {
                $checkNum = (int)substr($value['class_id'], -2);
                $min = $checkNum > $min ? $checkNum : $min;
            }
            $min = $min + 1;
            $class_id = empty($class_id) ? '' : $class_id;
            $childClass = $min > 9 ? $class_id . $min : $class_id . '0' . $min;
            return $childClass;
        } catch (\Exception $e) {
            return $class_id . '01';
        }
    }

    /**
     * 根据class_id获取当前栏目下最大排序序号
     * @param sting $class_id
     * @return sting
     */
    public function getMaxSort($class_id)
    {
        $where = array();
        $tier_id = strlen($class_id) / 2;
        $faClass = substr($class_id, 0, -2);
        if (!empty($faClass)) {
            $where['class_id'] = array('like', $faClass . '%', 'AND');
        }
        $where['tier_id'] = $tier_id;
        $maxSort = $this->where($where)->max('orderby');
        return $maxSort;
    }

    /**
     * 根据class_id获取当前栏目下最小拍序序号
     * @param sting $class_id
     * @return sting
     */
    public function getMinSort($class_id)
    {
        $where = array();
        $tier_id = strlen($class_id) / 2;
        $faClass = substr($class_id, 0, -2);
        if (!empty($faClass)) {
            $where['class_id'] = array('like', $faClass . '%', 'AND');
        }
        $where['tier_id'] = $tier_id;
        $minSort = $this->where($where)->min('orderby');
        return $minSort;
    }

    /**
     * 获取当前类别orderby
     * 比如class_id 是0101 则取得是01下面的最大排序值
     * @param int $class_id
     * @return orderby
     */
    public function getMenuOrderby($class_id)
    {
        $tier_id = strlen($class_id) / 2;
        $faClass = substr($class_id, 0, -2);
        if (!empty($faClass)) {
            $where['class_id'] = array('like', $faClass . '%', 'AND');
        }
        $where['tier_id'] = $tier_id;
        $orderby = $this->where($where)->max('orderby');
        $orderby = empty($orderby) ? 0 : $orderby;
        return $orderby;
    }

    /**
     * 删除信息
     * @param type $id
     * @return type
     */
    public function delMenu($id)
    {
        $chenkChild = $this->checkChild($id);
        if ($chenkChild) {
            throw_exception('还有子目录的目录不能删除');
        }
        $where['id'] = $id;
        $res = $this->where($where)->delete();
        return $res;
    }

    /**
     * 判断一个目录是不是还有子目录
     * @param int $id 目录id
     * @return boolean true 有  false 没有
     */
    public function checkChild($id)
    {
        $menuInfo = $this->getMenuInfo($id);
        //判断该目录下有没有子目录
        $childArray = array();
        if (!empty($menuInfo['class_id'])) {
            $childArray = $this->getMenuList4ClassId($menuInfo['class_id']);
        }
        if (count($childArray) > 0) {
            return TRUE;
        }
        return FALSE;
    }

    /**
     * 通过class_id得到权限列表
     * @param string $class_id
     * @return array
     */
    public function getAtom4PageMenuId($class_id = '', $offset = '0', $length = '10', $where = array())
    {
        $menuAllList = $this->getMenuList4ClassId($class_id, 100);
        $atomList = array();
        $permissionAtomObj = new \Admin\Model\AdminAtomModel();

        if (strlen($class_id) == 6) { //如classid为3级，则直接通过class_id查询
            try {
                $atomMiddle = $permissionAtomObj->getAtomList4MenuID($class_id, 'orderby ASC', $where);

            } catch (\Exception $e) {
                if ($e->getMessage() == '没有相关权限数据') {
                    return;
                }
            }
            if (is_array($atomMiddle)) {
                foreach ($atomMiddle as $k => $v) {
                    $atomMiddle[$k]['className'] = $this->getClassName($class_id);
                }
                $atomList = array_merge($atomList, $atomMiddle);
            }
        } else {
            foreach ($menuAllList as $key => $value) {
                try {
                    $atomMiddle = $permissionAtomObj->getAtomList4MenuID($value['class_id'], 'orderby ASC', $where);

                } catch (\Exception $e) {
                    if ($e->getMessage() == '没有相关权限数据') {
                        continue;
                    }
                }
                if (is_array($atomMiddle)) {
                    foreach ($atomMiddle as $k => $v) {
                        $atomMiddle[$k]['className'] = $this->getClassName($value['class_id']);
                    }
                    $atomList = array_merge($atomList, $atomMiddle);
                }
            }
        }
        $atomCount = count($atomList); //总条数
        $atomPageList = $data = array();
        $arrLen = ($offset * $length + $length) > $atomCount ? $atomCount : $offset * $length + $length;
        for ($i = $offset * $length; $i < $arrLen; $i++) { //输出翻页数据
            $atomPageList[] = $atomList[$i];
        }
        $data['atomCount'] = $atomCount;
        $data['atomPageList'] = $atomPageList;
        return $data;
    }

    /**
     * 通过class_id得到权限列表
     * @param string $class_id
     * @return array
     */
    public function getAtom4MenuId($class_id = '')
    {
        $menuAllList = $this->getMenuList4ClassId($class_id, 100);
        $atomList = array();
        $permissionAtomObj = new \Admin\Model\AdminAtomModel();
        //如classid为3级，则直接通过class_id查询
        if (strlen($class_id) == 6) {
            try {
                $atomMiddle = $permissionAtomObj->getAtomList4MenuID($class_id);

            } catch (\Exception $e) {
                if ($e->getMessage() == '没有相关权限数据') {
                    return;
                }
            }
            if (is_array($atomMiddle)) {
                foreach ($atomMiddle as $k => $v) {
                    $atomMiddle[$k]['className'] = $this->getClassName($class_id);
                }
                $atomList = array_merge($atomList, $atomMiddle);
            }
        } else {
            foreach ($menuAllList as $key => $value) {
                try {
                    $atomMiddle = $permissionAtomObj->getAtomList4MenuID($value['class_id']);

                } catch (\Exception $e) {
                    if ($e->getMessage() == '没有相关权限数据') {
                        continue;
                    }
                }
                if (is_array($atomMiddle)) {
                    foreach ($atomMiddle as $k => $v) {
                        $atomMiddle[$k]['className'] = $this->getClassName($value['class_id']);
                    }
                    $atomList = array_merge($atomList, $atomMiddle);

                }
            }
        }
        return $atomList;
    }

    /**
     * 得到class_id的所有父的名字，多个以|分隔
     * @param sting $class_id
     * @return string
     */
    public function getClassName($class_id)
    {
        $len = strlen($class_id);
        $className = '';
        for ($i = 2; $i <= $len; $i += 2) {
            $faClass = substr($class_id, 0, $i);
            $menuInfo = $this->where(array('class_id' => $faClass))->find();
            $className .= $menuInfo['name'] . '|';
        }
        return substr($className, 0, -1);
    }

    /**
     * 目录排序(单步向上)
     * @param String $id
     * @return boole
     */
    public function sortMenuUp($id)
    {
        $sortResult = $this->sortMenu($id, 'up');
        if ($sortResult) {
            return TRUE; //返回排序结果
        }
    }

    /**
     * 目录排序(单步向下)
     * @param String $id
     * @return boole
     */
    public function sortMenuDown($id)
    {
        $sortResult = $this->sortMenu($id, 'down');
        if ($sortResult) {
            return TRUE; //返回排序结果
        }
    }

    /**
     * 目录排序公用部分
     * @param Array $MenuInfo ,$where
     * @return boole
     */
    protected function sortMenu($id, $type)
    {
        $menuInfo = $this->getMenuInfo($id);
        //增加约束条件，保证查询的菜单都是同级别的
        $where['tier_id'] = $menuInfo['tier_id'];
        $where['orderby'] = $type == 'up' ? array('lt', $menuInfo['orderby']) : array('gt', $menuInfo['orderby']);        //查找上一个或下一个节点
        $rank = $type == 'up' ? 'desc' : 'asc';

        if ($menuInfo['tier_id'] != 1) {
            //匹配属于同一个父层级的节点class_id
            $newstr = substr($menuInfo['class_id'], 0, strlen($menuInfo['class_id']) - 2);
            $where['class_id'] = array('like', $newstr . '%'); //创建like匹配条件
        }
        $beSortNode = $this->where($where)->order('orderby ' . $rank)->find();
        if (!empty($beSortNode['id'])) { //判断被排序的节点是否还有数据，最顶部或最底部就没有数据了
            if ($beSortNode['orderby'] > $menuInfo['orderby']) {
                $largerId = $beSortNode['id'];
                $smallId = $menuInfo['id'];
                $largerOrderby = $beSortNode['orderby'];
                $smallOrderby = $menuInfo['orderby'];
            } else {
                $largerId = $menuInfo['id'];
                $smallId = $beSortNode['id'];
                $largerOrderby = $menuInfo['orderby'];
                $smallOrderby = $beSortNode['orderby'];
            }
            $sortDataB = array();
            $sortDataS = array();
            $sortDataB['orderby'] = $largerOrderby; //大小两个节点排序序号互换
            $sortDataB['id'] = $smallId;
            $this->save($sortDataB);
            $sortDataS['orderby'] = $smallOrderby;
            $sortDataS['id'] = $largerId;
            $this->save($sortDataS);
            return TRUE;
        } else {
            throw new \Exception('已经是最顶部或最底部');
        }
    }


    public function doSave($dataArray)
    {
        if (empty($dataArray['id'])) {
            $dataArray['orderby'] = $this->getMenuOrderby($dataArray['class_id']) + 1;
        }
        $dataArray['tier_id'] = strlen($dataArray['class_id']) / 2;
        if (false === $this->create($dataArray)) {
            throw new \Exception($this->getError());
        }
        if (empty($dataArray['id'])) {
            $res = $this->add($dataArray);
        } else {
            $res = $this->save($dataArray);
        }
        return $res;
    }

    protected function _after_delete(&$data, $options)
    {

    }

    protected function _after_update($data, $options)
    {

    }

    protected function _after_insert($data, $options)
    {

    }
}

?>